package management

import (
	"context"
	"encoding/json"
	"fmt"
	"net/http"
	"reflect"
	"strconv"
	"time"

	"github.com/gorilla/mux"
	"github.com/jsrccb/nachuan/common"
	"github.com/tealeg/xlsx"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/bson/primitive"
	"go.mongodb.org/mongo-driver/mongo"
	"go.mongodb.org/mongo-driver/mongo/options"
)

type CustomTraceMgr struct {
	client                *mongo.Client
	customTraceCollection *mongo.Collection
}

var (
	G_CustomTraceMgr *CustomTraceMgr
)

func initCustomTraceApi(r *mux.Router) {
	s := r.PathPrefix("/customtrace").Subrouter()
	// s.HandleFunc("/list", UserListHandler)
	s.HandleFunc("/updsave", handleCustomTraceInfo)
	s.HandleFunc("/del", handleDelCustomTrace)
	//请求/clue/query?clueno=xxx
	s.HandleFunc("/query", handleQueryCustomTraceInfo)

	s.HandleFunc("/download", handleDownloadCustomTraceInfo)
}

func (CustomTraceMgr *CustomTraceMgr) delCustomTrace(id string) (err error) {

	_, err = CustomTraceMgr.customTraceCollection.DeleteOne(context.TODO(), bson.D{{"id", id}}, &options.DeleteOptions{})

	// fmt.Println("doccount:" + strconv.FormatInt(doccount, 10))
	return
}

func (CustomTraceMgr *CustomTraceMgr) saveCustomTrace(customTrace *common.CustomTrace) (err error) {

	_, err = CustomTraceMgr.customTraceCollection.InsertOne(context.TODO(), customTrace)

	return
}

func (CustomTraceMgr *CustomTraceMgr) updCustomTrace(customTrace *common.CustomTrace) (err error) {

	_, err = CustomTraceMgr.customTraceCollection.UpdateOne(context.TODO(), bson.D{{"id", customTrace.ID}}, bson.M{"$set": customTrace})

	return
}

func handleDownloadCustomTraceInfo(resp http.ResponseWriter, req *http.Request) {
	var (
		outfile  string
		err      error
		querySet []bson.M
		// skipParam   string
		// rolelimit     *common.RoleLimits

		queryBson bson.M

		// bdquery   bson.D

		begintracedate string
		endtracedate   string
		x              interface{}
		row            *xlsx.Row
		customtraces   []*common.CustomTrace
		customtrace    *common.CustomTrace
		bytes          []byte
	)

	query := req.URL.Query()

	begintracedate = query.Get("begintracedate")
	endtracedate = query.Get("endtracedate")

	if begintracedate != "" {
		q_begintracedate := bson.M{"nextTraceDate": bson.M{"$gte": begintracedate}}
		querySet = append(querySet, q_begintracedate)
		// setElements = append(setElements, bson.E{"createTime", createtime})
	}

	if endtracedate != "" {
		q_endtracedate := bson.M{"nextTraceDate": bson.M{"$lte": endtracedate}}
		querySet = append(querySet, q_endtracedate)
		// setElements = append(setElements, bson.E{"createTime", createtime})
	}

	queryBson = bson.M{"$and": querySet}

	if customtraces, err = G_CustomTraceMgr.queryCustomTraceDownloadbySet(queryBson); err != nil {
		// goto ERR
	}

	outfile = "./downloadfile/customtrace" + common.BuildDateTodayStr4() + ".xlsx"
	f := xlsx.NewFile()
	sheet, _ := f.AddSheet("clue")
	for idx, _ := range customtraces {
		// fmt.Println(idx)
		//写表头
		// fmt.Println(1111 + idx)
		if idx == 0 {
			// fmt.Println(idx)
			x = customtraces[idx]
			row = sheet.AddRow()
			// reflect.ValueOf(custominfo)
			// v := reflect.ValueOf(&custominfo)
			// n := reflect.ValueOf(&custominfo).NumField()
			t := reflect.TypeOf(x)
			if t.Kind() == reflect.Ptr {
				t = t.Elem()
			}
			// fmt.Println(t.Kind())
			if t.Kind() != reflect.Struct {
				fmt.Println("Check type error not Struct")
				return
			}
			n := t.NumField()
			for i := 0; i < n; i = i + 1 {
				cell := row.AddCell()
				cell.SetValue(t.Field(i).Tag.Get("uname"))
			}
		}

		row = sheet.AddRow()
		customtrace = customtraces[idx]
		row.WriteStruct(customtrace, -1)
	}
	if err = f.Save(outfile); err != nil {
		// goto ERR
	}

	cluemap := make(map[string]interface{})
	// cluemap["cluecount"] = countclue
	// cluemap["filepath"] = outfile[1:]
	cluemap["filepath"] = G_config.FileUrl + ":" + strconv.Itoa(G_config.ApiPort) + "/downloadfile/customtrace" + common.BuildDateTodayStr4() + ".xlsx"

	if bytes, err = common.BuildResponse(0, "success", cluemap); err == nil {
		resp.Write(bytes)
	} else {
		goto ERR
	}

	return
ERR:
	if bytes, err = common.BuildResponse(-1, err.Error(), nil); err == nil {
		resp.Write(bytes)
	}

}

func (customTraceMgr *CustomTraceMgr) queryCustomTraceDownloadbySet(setElements bson.M) (customtraceinfos []*common.CustomTrace, err error) {

	var (
		// resultOne *mongo.InsertOneResult
		cursor          *mongo.Cursor
		customtrace     *common.CustomTrace
		findopt         *options.FindOptions
		ctx             context.Context
		customtraceSort *common.SortLogByClueNo
		// update *common.HostInfo
	)

	ctx, _ = context.WithTimeout(context.Background(), 60*time.Second)

	findopt = &options.FindOptions{}
	customtraceSort = &common.SortLogByClueNo{
		SortOrder: -1,
	}
	findopt.SetSort(customtraceSort)
	// findopt.SetLimit(10000)
	// findopt.SetSkip(0)
	findopt.SetBatchSize(3000)

	if len(setElements["$and"].([]primitive.M)) == 0 {
		// fmt.Println(0000000)
		cursor, err = customTraceMgr.customTraceCollection.Find(context.TODO(), bson.D{}, findopt)
	} else {
		cursor, err = customTraceMgr.customTraceCollection.Find(context.TODO(), setElements, findopt)
	}
	defer cursor.Close(ctx)

	// cursor.Decode(&clueinfos)
	// var i int
	for cursor.Next(ctx) {
		customtrace = &common.CustomTrace{}
		if err = cursor.Decode(customtrace); err != nil {
			fmt.Println(err.Error())
			continue
		}
		// i = i + 1
		// fmt.Println(i)
		// fmt.Println(clueinfo)
		// clueinfo.CluePhone = ""
		customtraceinfos = append(customtraceinfos, customtrace)
	}
	// fmt.Println("doccount:" + strconv.FormatInt(doccount, 10))
	return
}

func (CustomTraceMgr *CustomTraceMgr) queryCustomTraceById(id string) (customTraceInfo *common.CustomTrace, err error) {

	var (
		// resultOne *mongo.InsertOneResult
		filter *common.CustomTraceIdFilter
		result *mongo.SingleResult

		// update *common.HostInfo
	)
	// fmt.Println("clueNo:", clueNo)

	filter = &common.CustomTraceIdFilter{
		ID: id,
	}

	result = CustomTraceMgr.customTraceCollection.FindOne(context.TODO(), filter, &options.FindOneOptions{})
	result.Decode(&customTraceInfo)
	// fmt.Println("clueInfo:", clueInfo)
	return
}

func (CustomTraceMgr *CustomTraceMgr) queryCustomTracebycustomNo(customNo string, skip int64, limit int64) (customTraceInfo []*common.CustomTrace, err error) {

	var (
		// resultOne *mongo.InsertOneResult
		cursor          *mongo.Cursor
		customtraceinfo *common.CustomTrace
		findopt         *options.FindOptions
		ctx             context.Context
		filter          *common.CustomNoFilter
		clueSort        *common.SortLogByClueNo
		// update *common.HostInfo
	)

	ctx, _ = context.WithTimeout(context.Background(), 10*time.Second)

	findopt = &options.FindOptions{}
	clueSort = &common.SortLogByClueNo{
		SortOrder: -1,
	}
	findopt.SetSort(clueSort)
	if limit > 0 && skip >= 0 {
		findopt.SetLimit(limit)
		findopt.SetSkip(limit * skip)

	} else {
		return
	}

	filter = &common.CustomNoFilter{
		CustomNo: customNo,
	}

	// fmt.Println(setElements)
	// fmt.Println(setElements.Map())
	cursor, err = CustomTraceMgr.customTraceCollection.Find(context.TODO(), filter, findopt)

	defer cursor.Close(ctx)

	for cursor.Next(ctx) {
		customtraceinfo = &common.CustomTrace{}
		if err = cursor.Decode(customtraceinfo); err != nil {
			continue
		}
		customTraceInfo = append(customTraceInfo, customtraceinfo)
	}
	// fmt.Println("doccount:" + strconv.FormatInt(doccount, 10))
	return
}

func handleQueryCustomTraceInfo(resp http.ResponseWriter, req *http.Request) {
	var (
		err             error
		bytes           []byte
		customNo        string
		customtraceinfo []*common.CustomTrace
		skipParam       string
		limitParam      string
		skip            int
		limit           int
		// rolelimit     *common.RoleLimits
	)

	query := req.URL.Query()
	customNo = query.Get("customno")
	skipParam = query.Get("skip")
	limitParam = query.Get("limit")

	if skip, err = strconv.Atoi(skipParam); err != nil {
		skip = 0
	}

	if limit, err = strconv.Atoi(limitParam); err != nil {
		limit = 100
	}

	if customNo != "" {
		customtraceinfo, _ = G_CustomTraceMgr.queryCustomTracebycustomNo(customNo, int64(skip), int64(limit))
		if bytes, err = common.BuildResponse(0, "success", customtraceinfo); err == nil {
			resp.Write(bytes)
		} else {
			goto ERR
		}
		return
	}
	return
ERR:
	if bytes, err = common.BuildResponse(-1, err.Error(), nil); err == nil {
		resp.Write(bytes)
	}
}

func handleDelCustomTrace(resp http.ResponseWriter, req *http.Request) {
	var (
		err   error
		bytes []byte
		id    string
	)

	query := req.URL.Query()
	id = query.Get("id")
	// fmt.Println(clueNo)

	// fmt.Println(clueinfo)
	if err = G_CustomTraceMgr.delCustomTrace(id); err == nil {
		if bytes, err = common.BuildResponse(0, "success", "删除客户追踪成功"); err == nil {
			resp.Write(bytes)
		}
	} else {
		goto ERR
	}
	return
ERR:
	if bytes, err = common.BuildResponse(-1, err.Error(), nil); err == nil {
		resp.Write(bytes)
	}
}

func handleCustomTraceInfo(resp http.ResponseWriter, req *http.Request) {
	var (
		err             error
		bytes           []byte
		customTraceinfo *common.CustomTrace
		customtracestr  string
		// rolelimit     *common.RoleLimits
	)

	if err = req.ParseForm(); err != nil {
		goto ERR
	}
	customtracestr = req.PostForm.Get("customtraceinfo")
	if err = json.Unmarshal([]byte(customtracestr), &customTraceinfo); err != nil {
		goto ERR
	}

	if customTraceinfo.TraceDate == "" {
		customTraceinfo.TraceDate = common.BuildDateTodayStr2()
	}

	if customTraceinfo.ID == "" {
		customTraceinfo.ID = common.BuildUUID()
		if err = G_CustomTraceMgr.saveCustomTrace(customTraceinfo); err == nil {

			if bytes, err = common.BuildResponse(0, "success", customTraceinfo); err == nil {
				resp.Write(bytes)
			}
		} else {
			if bytes, err = common.BuildResponse(-1, err.Error(), "新增客户跟踪异常"); err == nil {
				resp.Write(bytes)
			}
		}
	} else {
		if err = G_CustomTraceMgr.updCustomTrace(customTraceinfo); err == nil {
			if bytes, err = common.BuildResponse(0, "success", customTraceinfo); err == nil {
				resp.Write(bytes)
			}
		} else {
			if bytes, err = common.BuildResponse(-1, err.Error(), "修改客户跟踪异常"); err == nil {
				resp.Write(bytes)
			}
		}
	}
	return
ERR:
	if bytes, err = common.BuildResponse(-1, err.Error(), nil); err == nil {
		resp.Write(bytes)
	}
}

func InitCustomTraceMgr() (err error) {

	G_CustomTraceMgr = &CustomTraceMgr{
		client:                G_MongoMgr.client,
		customTraceCollection: G_MongoMgr.MongdbConnect.Collection("customtrace"),
	}

	// fmt.Println("init userMgr")

	return

}
